package edu.kit.csl.cratyli.ui;

/**
 * Singleton class for logging.
 */
public class Logger {

	/**
	 * Logging level for debug information.
	 */
	static public final int DEBUG = 1;
	
	/**
	 * Logging level for notices and general information.
	 */
	static public final int NOTICE = 2;
	
	/**
	 * Logging level for warnings.
	 */
	static public final int WARNING = 3;
	
	/**
	 * Logging level for errors.
	 */
	static public final int ERROR = 4;
	
	/**
	 * Logging for fatal errors. After fatal errors, the program execution
	 * is not possible anymore.
	 */
	static public final int FATAL_ERROR = 5;
	
	/*
	 * String identifier for log levels
	 */
	static private final String strings[] = {
		"ALL",
		"DEBUG",
		"INFO",
		"WARN",
		"ERROR",
		"FATAL"
		};
	
	/*
	 * Singleton instance.
	 */
	static private Logger log;
	
	/*
	 * TRUE if a fatal error was reported
	 * 
	 * @see #fatalError()
	 */
	private boolean fatalErrorRegistered;
	
	/*
	 * Logging level
	 */
	private int level;
	
	/*
	 * Private constructor.
	 */
	private Logger() {
		fatalErrorRegistered = false;
		level = Logger.NOTICE;
	}
	
	/**
	 * Get logging singleton. If it does not exist yet, create it.
	 */
	static public Logger getSingleton() {
		if (log == null) {
			log = new Logger();
		}
		return log;
	}
	
	/**
	 * Log a fatal error.
	 * 
	 * @param msg logging message
	 */
	public void fatalError(String msg) {
		fatalErrorRegistered = true;
		log(msg, Logger.FATAL_ERROR);
	}
	
	/**
	 * Returns true if a fatal error was reported yet.
	 * 
	 * @return TRUE if {@link #fatalError(String)} was called already, FALSE
	 * 			otherwise
	 * @see #fatalError(String)
	 */
	public boolean isFatalErrorRegistered() {
		return fatalErrorRegistered;
	}
	
	/**
	 * Log a message on Logger.NOTICE level.
	 * 
	 * @param msg logging message
	 */
	public void notice(String msg) {
		log(msg, Logger.NOTICE);
	}
	
	/**
	 * Log a message on Logger.ERROR level.
	 * 
	 * @param msg logging message
	 */
	public void error(String msg) {
		log(msg, Logger.ERROR);
	}
	
	/**
	 * Log a message on Logger.WARNING level.
	 * 
	 * @param msg logging message
	 */
	public void warn(String msg) {
		log(msg, Logger.WARNING);
	}
	
	/**
	 * Log a message on Logger.DEBUG level.
	 * 
	 * @param msg logging message
	 */
	public void debug(String msg) {
		log(msg, Logger.DEBUG);
	}
	
	/**
	 * Log a message.
	 * 
	 * @param msg logging message
	 * @param level log level (one of the Logger.* constants)
	 */
	public void log(String msg, int level) {
		if (level >= this.level) {
			System.out.println(strings[level] + ": " + msg);
		}
	}
	
	/**
	 * Set logging level. All message greater or equal the given level
	 * will be written.
	 * 
	 * @param level the new logging level (one of the Logger.* constants)
	 */
	public void setLevel(int level) {
		this.level = level;
	}
	
	/**
	 * Set logging level using its name. All message greater or equal the 
	 * given level will be written. Do not change the level if the name
	 * does not match any level.
	 * 
	 * @param name the name of the new level
	 */
	public void setLevel(String name) {
		for (int i = 0; i < strings.length; i++) {
			if (strings[i].equals(name)) {
				this.level = i;
				return;
			}
		}
	}
	
	/**
	 * Get the current logging level.
	 * 
	 * @return the current logging level (one of the Logger.* constants)
	 */
	public int getLevel() {
		return level;
	}
}
